﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Threading;
using System.IO;

namespace Serveur
{
    class Program
    {
        static ArrayList acceptList = new ArrayList(); //liste des clients
        static ArrayList readList = new ArrayList(); //liste des info envoyer par client

        static Socket CurrentClient = null;
        static Socket SendClient = null;
        static byte[] msg;
        static bool lectureEnCours;
        static Thread ecoute = new Thread(Program.Ecoute);

        static int compt = 0;//compte les clients
        static byte[] clientData;

        static void Main(string[] args)
        {
            Console.WriteLine("Lancement des threads");
            ecoute.Start();
            Thread th_start = new Thread(Program.Start);
            th_start.Start(); //lancement du thread dattente des clients
            Thread testco = new Thread(Program.TestCo);
            testco.Start();
        }

        public static void Start()
        {
            int port = 8000;
            IPHostEntry ipHostEntry = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAddress = ipHostEntry.AddressList[0];

            Console.WriteLine((ipHostEntry.AddressList[0]));

            IPEndPoint ipServer = new IPEndPoint(ipAddress, port); //passage des parametre pour lecoute
            TcpListener socket_ecoute = new TcpListener(ipServer); //initialisation
            socket_ecoute.Start(); //demarrage de lecoute
            while (true)
            {
                Console.WriteLine("Attente des clients...");
                CurrentClient = socket_ecoute.AcceptSocket(); //methode bloquante
                ecoute.Suspend();
                Console.WriteLine("New Client :" + CurrentClient.GetHashCode());
                acceptList.Add(CurrentClient);
                if (compt == 0)
                {
                    byte[] debug = new byte[1024 * 10];
                    do
                    {
                        clientData = new byte[1024 * 10];
                        CurrentClient.Receive(clientData);
                        int fileNameLen = BitConverter.ToInt32(clientData, 0);
                        string fileName = System.Text.Encoding.ASCII.GetString(clientData, 4, fileNameLen);
                        Console.WriteLine(fileName);
                    } while (clientData == debug);
                }
                else
                {
                    CurrentClient.Send(clientData, clientData.Length, SocketFlags.None);
                }
                compt++;
                //CurrentClient.Send(BitConverter.GetBytes(CurrentClient.GetHashCode()), (BitConverter.GetBytes(CurrentClient.GetHashCode())).Length, SocketFlags.None);
                ecoute.Resume();
            }
        }

        public static void writeToAll()
        {
            SendMsg(msg);
        }

        public static void Ecoute()
        {
            while (true)
            {
                readList.Clear(); //nettoie la liste

                for (int i = 0; i < acceptList.Count; i++) //verifie si un client envoi une donnee
                {
                    readList.Add((Socket)acceptList[i]);
                }

                if (readList.Count > 0) //si il en trouve
                {
                    Socket.Select(readList, null, null, 1000);
                    for (int i = 0; i < readList.Count; i++)
                    {
                        if (((Socket)readList[i]).Available > 0)
                        {
                            lectureEnCours = true;
                            while (((Socket)readList[i]).Available > 0)
                            {
                                SendClient = (Socket)readList[i];
                                msg = new byte[((Socket)readList[i]).Available]; //prepare le tableau
                                ((Socket)readList[i]).Receive(msg, msg.Length, SocketFlags.None); //recoit les donnés dans la tableau

                               //string message = System.Text.Encoding.UTF8.GetString(msg);
                               //Console.WriteLine(message);
                                //msg = System.Text.Encoding.UTF8.GetBytes(message);


                                Thread sendtoall = new Thread(new ThreadStart(Program.writeToAll)); //lancement du thread d'ecriture
                                sendtoall.Start();
                                sendtoall.Join(); //stop temporairement le thread en cours
                                
                            }
                            lectureEnCours = false;
                        }
                    }

                }
                Thread.Sleep(15);
            }
        }

        public static void TestCo() //regarde si les clients sont toujours co avec la methode Poll
        {
            while (true)
            {

                for (int i = 0; i < acceptList.Count; i++)
                {
                    if (((Socket)acceptList[i]).Poll(10, SelectMode.SelectRead) && ((Socket)acceptList[i]).Available == 0)
                    {
                        if (!lectureEnCours)
                        {
                            Console.WriteLine("Deco " + acceptList[i].GetHashCode());
                            ((Socket)acceptList[i]).Close(); //ferme la connexion avec le client
                            acceptList.Remove(((Socket)acceptList[i]));
                            i--;
                            compt--;
                        }

                    }
                }
                Thread.Sleep(5);
            }
        }

        public static void SendMsg(byte[] msg)
        {
            for (int i = 0; i < acceptList.Count; i++)
            {
                if (((Socket)acceptList[i]).Connected) //verifie si le client est toujours connecte
                {
                    if ((Socket)acceptList[i] != SendClient)
                    {
                        try
                        {
                            int bytesend = ((Socket)acceptList[i]).Send(msg, msg.Length, SocketFlags.None);
                        }
                        catch
                        {
                        }
                    }
                }
                else
                {
                    acceptList.Remove((Socket)acceptList[i]);
                    i--;
                    compt--;
                }
            }
        }
    }
}
